home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 October: Mac OS SDK / Dev.CD Oct 00 SDK1.toast / Development Kits / Cross Platform / QuickTime 4.1.2 Windows SDK / CIncludes / Debugging.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-12  |  30.4 KB  |  798 lines  |  [TEXT/R*ch]

  1. /*
  2.      File:        Debugging.h
  3.  
  4.      Contains:    Macros to handle exceptions and assertions.
  5.  
  6.      Version:    Technology:    Carbon
  7.                  Release:    QuickTime 4.1
  8.  
  9.      Copyright:    (c) 1989-1999 by Apple Computer, Inc., all rights reserved.
  10.  
  11.      Bugs?:        For bug reports, consult the following page on
  12.                  the World Wide Web:
  13.  
  14.                      http://developer.apple.com/bugreporter/
  15.  
  16. */
  17. #ifndef __DEBUGGING__
  18. #define __DEBUGGING__
  19.  
  20. #ifndef __MACTYPES__
  21.     #include <MacTypes.h>
  22. #endif
  23.  
  24. #ifndef __FILES__
  25.     #include <Files.h>
  26. #endif
  27.  
  28.  
  29. /*______________________________________________________________________________________*/
  30. /*                                                                                        */
  31. /*    This file defines standard exception handling and assertion macros for                */
  32. /*    system-level programming in C.  Originally used in QuickDraw GX, and heavily        */
  33. /*    modified since, these macros are used extensively throughout Mac OS system            */
  34. /*    software.  Now *you* can look and feel like a system software engineer.                */
  35. /*                                                                                        */
  36. /*    To activate debugger breaks, #define DEBUG to 1 (one) before including this file.    */
  37. /*    Five further levels of debugging are available, selected by #defining one            */
  38. /*    of the following conditionals to 1 after DEBUG is defined to 1.                        */
  39. /*                                                                                        */
  40. /*        DEBUG_INTERNAL        the default; includes file and line number information        */
  41. /*                                                                                        */
  42. /*        DEBUG_EXTERNAL        used for code which must ship to developers outside            */
  43. /*                            your organization; no file or line number information is    */
  44. /*                            included in asserts                                            */
  45. /*                                                                                        */
  46. /*        DEBUG_BREAK_ONLY    where an assertion would normally be sent to the debugger,     */
  47. /*                            send an empty string instead.                                 */
  48. /*                                                                                        */
  49. /*        PRODUCTION            used for shipping code; no debugger breaks are emitted        */
  50. /*                                                                                        */
  51. /*        PERFORMANCE            same as PRODUCTION                                            */
  52. /*                                                                                        */
  53. /*    #defining DEBUG to 0 is equivalent to #defining PRODUCTION 1 when DEBUG is 1.        */
  54. /*    (No code for debugger breaks is emitted in either case.)                            */
  55. /*                                                                                        */
  56. /*    Of the multitude of macros, the preferred ones are:                                    */
  57. /*                                                                                        */
  58. /*    debug_string(c-string)                                                                */
  59. /*        If debugging is on, c-string is printed in the debugger.                        */
  60. /*        In production builds, debug_string() does nothing.                                */
  61. /*                                                                                        */
  62. /*    check(expression)                                                                    */
  63. /*    check_noerr(error)                                                                    */
  64. /*        If (expression) evaluates to false, break into the debugger.                     */
  65. /*        In production builds, check() does nothing.                                        */
  66. /*        Code inside check() statements is not compiled into production builds.            */
  67. /*                                                                                        */
  68. /*    require(expression, label)                                                            */
  69. /*    require_noerr(expression, label)                                                    */
  70. /*        If (expression) evaluates to false, announce this fact via the                    */
  71. /*        debugger and then goto label.  In production builds, does not call                */
  72. /*        the debugger but still goes to label if expression is false.                    */
  73. /*                                                                                        */
  74. /*    require_action(expression, label, action)                                            */
  75. /*    require_noerr_action(expression, label, action)                                        */
  76. /*        Same as require, but executes (action) before jumping to label.                    */
  77. /*                                                                                        */
  78. /*    check_string(expression, c-string)                                                    */
  79. /*    require_string(expression, label, c-string)                                            */
  80. /*    require_noerr_string(expression, label, c-string)                                    */
  81. /*        If expression evaluates to false, print string and then proceed as in             */
  82. /*        a normal check/require statement                                                */
  83. /*                                                                                        */
  84. /*    verify(expression)                                                                    */
  85. /*    verify_noerr(error)                                                                    */
  86. /*        If debugging is on, verify is the same as check(expression).                    */
  87. /*        If debugging is off, verify still evaluates (expression)                        */
  88. /*        but ignores the result.  Code inside verify() statements                         */
  89. /*        is executed in both production and debug builds.                                */
  90. /*                                                                                        */
  91. /*    Common usage:                                                                        */
  92. /*                                                                                        */
  93. /*        // my pixmap is not purgeable, so locking it should never fail                    */
  94. /*        verify( LockPixels(myPixMap) );                                                    */
  95. /*        verify_noerr( DisposeThread(myThread, &threadResult, true) );                    */
  96. /*______________________________________________________________________________________*/
  97.  
  98. /*______________________________________________________________________________________*/
  99. /*                                                                                        */
  100. /* Before including this file, #define kCompentSignatureString to a C-string            */
  101. /* containing the name of your client.                                                    */
  102. /*                                                                                        */
  103. /* example: #define kComponentSignatureString "SurfWriter"                                */
  104. /*______________________________________________________________________________________*/
  105.  
  106. #ifndef kComponentSignatureString
  107. #define kComponentSignatureString "Third Party Client"
  108. #endif
  109.  
  110.  
  111.  
  112. #define DEBUG_LEVEL_PRODUCTION    0
  113. #define DEBUG_LEVEL_BREAK_ONLY    1
  114. #define DEBUG_LEVEL_EXTERNAL    3
  115. #define DEBUG_LEVEL_INTERNAL    4
  116. #define DEBUGFULL                DEBUG_LEVEL_INTERNAL
  117. #define DEBUG_NO_OPTIONS        0
  118.  
  119.  
  120. #ifdef DEBUGLEVEL
  121. #undef DEBUGLEVEL
  122. #endif
  123.  
  124. #if DEBUG
  125.     #if     PRODUCTION
  126.         #define DEBUGLEVEL DEBUG_LEVEL_PRODUCTION
  127.     #elif    DEBUG_EXTERNAL
  128.         #define DEBUGLEVEL DEBUG_LEVEL_EXTERNAL
  129.     #elif    DEBUG_INTERNAL
  130.         #define DEBUGLEVEL DEBUG_LEVEL_INTERNAL
  131.     #elif    PERFORMANCE
  132.         #define DEBUGLEVEL DEBUG_LEVEL_PRODUCTION
  133.     #elif    DEBUG_BREAK_ONLY
  134.         #define DEBUGLEVEL DEBUG_LEVEL_BREAK_ONLY
  135.     #else
  136.         #define DEBUGLEVEL DEBUG_LEVEL_INTERNAL
  137.     #endif
  138. #endif
  139.  
  140. #ifndef    DEBUGLEVEL
  141. #define DEBUGLEVEL DEBUG_LEVEL_PRODUCTION
  142. #endif
  143.  
  144.  
  145. #ifndef COMPONENT_SIGNATURE
  146. #define COMPONENT_SIGNATURE '?*?*'
  147. #endif
  148.  
  149.  
  150.  
  151. #define QuoteExceptionString(x) #x
  152.  
  153.  
  154. /*______________________________________________________________________________________*/
  155. /*                                                                                        */
  156. /*    DEBUGASSERTMSG - all error reporting is routed through this macro, which calls the    */
  157. /*    system routine DebugAssert().  If you wish to use your own assertion/debugger break    */
  158. /*    routine, you can override DEBUGASSERTMSG by defining it before including this file.    */
  159. /*______________________________________________________________________________________*/
  160.  
  161.  
  162. #if PRAGMA_ONCE
  163. #pragma once
  164. #endif
  165.  
  166. #ifdef __cplusplus
  167. extern "C" {
  168. #endif
  169.  
  170. #if PRAGMA_IMPORT
  171. #pragma import on
  172. #endif
  173.  
  174. #if PRAGMA_STRUCT_ALIGN
  175.     #pragma options align=mac68k
  176. #elif PRAGMA_STRUCT_PACKPUSH
  177.     #pragma pack(push, 2)
  178. #elif PRAGMA_STRUCT_PACK
  179.     #pragma pack(2)
  180. #endif
  181.  
  182. EXTERN_API( void )
  183. DebugAssert                        (OSType                 componentSignature,
  184.                                  UInt32                 options,
  185.                                  char *                    assertionString,
  186.                                  char *                    exceptionString,
  187.                                  char *                    errorString,
  188.                                  char *                    fileName,
  189.                                  long                     lineNumber,
  190.                                  void *                    value)                                TWOWORDINLINE(0x7000, 0xAA7E);
  191.  
  192.  
  193. #ifndef DEBUGASSERTMSG
  194. #if DEBUGLEVEL == DEBUG_LEVEL_BREAK_ONLY
  195. #define DEBUGASSERTMSG(componentSignature, options, assertionString, exceptionString, errorString, fileName, lineNumber, value ) \
  196.     Debugger()
  197. #elif DEBUGLEVEL == DEBUG_LEVEL_EXTERNAL
  198. /* exclude code structure information */
  199. #if (applec && (!__powerc))
  200. #define DEBUGASSERTMSG(componentSignature, options, assertionString, exceptionString, errorString, fileName, lineNumber, value ) \
  201.     DebugAssert(componentSignature, options, kComponentSignatureString, assertionString, nil, nil, 0, value )
  202. #else
  203. #define DEBUGASSERTMSG(componentSignature, options, assertionString, exceptionString, errorString, fileName, lineNumber, value ) \
  204.     DebugAssert(componentSignature, options, kComponentSignatureString ": " assertionString, nil, nil, nil, 0, value )
  205. #endif
  206. #elif DEBUGLEVEL == DEBUG_LEVEL_INTERNAL
  207. /* include all info */
  208. #if (applec && (!__powerc))
  209. #define DEBUGASSERTMSG(componentSignature, options, assertionString, exceptionString, errorString, fileName, lineNumber, value ) \
  210.     DebugAssert(componentSignature, options, kComponentSignatureString, assertionString, nil, nil, 0, value )
  211. #else
  212. #define DEBUGASSERTMSG(componentSignature, options, assertionString, exceptionString, errorString, fileName, lineNumber, value ) \
  213.     DebugAssert(componentSignature, options, kComponentSignatureString ": " assertionString, exceptionString, errorString, fileName, lineNumber, value )
  214. #endif
  215. #else
  216. /* no debugger message */
  217. #define DEBUGASSERTMSG(componentSignature, options, assertionString, exceptionString, errorString, fileName, lineNumber, value )
  218. #endif
  219. #endif
  220.  
  221. /*
  222.       kBlessedBusErrorBait is an address that will never be mapped
  223.       by Mac OS 8 or 9. It is close to the middle of the 64K range from
  224.       0x68F10000 to 0x68F1FFFF that is unmapped and cannot be accessed 
  225.       without causing an exception. Thus, it's a good value to use for
  226.       filling uninitialized pointers, etc.
  227. */
  228. enum {
  229.     kBlessedBusErrorBait        = 0x68F168F1
  230. };
  231.  
  232.  
  233. /*    TaskLevel masks*/
  234. enum {
  235.     k68kInterruptLevelMask        = 0x00000007,
  236.     kInVBLTaskMask                = 0x00000010,
  237.     kInDeferredTaskMask            = 0x00000020,
  238.     kInSecondaryIntHandlerMask    = 0x00000040
  239. };
  240.  
  241. enum {
  242.     kComponentDebugOption        = 0                                /* optionSelectorNum to turn breaks for component on/off*/
  243. };
  244.  
  245. enum {
  246.     kGetDebugOption                = 1,                            /* get current debug option setting*/
  247.     kSetDebugOption                = 2                                /* set debug option*/
  248. };
  249.  
  250. /*
  251.       DebugComponentCallback
  252.       DebugComponentCallback is the callback into a component that registers with DebugLib.
  253.       It is called to get the debug option setting, or to turn a debug option on or off.
  254.           Inputs:
  255.               optionSelectorNum    The component debug option to set
  256.               command                The command:
  257.                                       kGetDebugOption        - get current debug option setting
  258.                                       kSetDebugOption        - set debug option
  259.           Outputs:
  260.               optionSetting        The current setting if kGetDebugOption;
  261.                                   the new debug option if kSetDebugOption
  262. */
  263. typedef CALLBACK_API( void , DebugComponentCallbackProcPtr )(SInt32 optionSelectorNum, UInt32 command, Boolean *optionSetting);
  264. typedef STACK_UPP_TYPE(DebugComponentCallbackProcPtr)             DebugComponentCallbackUPP;
  265. #if OPAQUE_UPP_TYPES
  266.     EXTERN_API(DebugComponentCallbackUPP)
  267.     NewDebugComponentCallbackUPP    (DebugComponentCallbackProcPtr userRoutine);
  268.  
  269.     EXTERN_API(void)
  270.     DisposeDebugComponentCallbackUPP    (DebugComponentCallbackUPP userUPP);
  271.  
  272.     EXTERN_API(void)
  273.     InvokeDebugComponentCallbackUPP    (SInt32                optionSelectorNum,
  274.                                     UInt32                    command,
  275.                                     Boolean *                optionSetting,
  276.                                     DebugComponentCallbackUPP userUPP);
  277.  
  278. #else
  279.     enum { uppDebugComponentCallbackProcInfo = 0x00000FC0 };         /* pascal no_return_value Func(4_bytes, 4_bytes, 4_bytes) */
  280.     #define NewDebugComponentCallbackUPP(userRoutine)                 (DebugComponentCallbackUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), uppDebugComponentCallbackProcInfo, GetCurrentArchitecture())
  281.     #define DisposeDebugComponentCallbackUPP(userUPP)                 DisposeRoutineDescriptor(userUPP)
  282.     #define InvokeDebugComponentCallbackUPP(optionSelectorNum, command, optionSetting, userUPP)  CALL_THREE_PARAMETER_UPP((userUPP), uppDebugComponentCallbackProcInfo, (optionSelectorNum), (command), (optionSetting))
  283. #endif
  284. /* support for pre-Carbon UPP routines: NewXXXProc and CallXXXProc */
  285. #define NewDebugComponentCallbackProc(userRoutine)                 NewDebugComponentCallbackUPP(userRoutine)
  286. #define CallDebugComponentCallbackProc(userRoutine, optionSelectorNum, command, optionSetting) InvokeDebugComponentCallbackUPP(optionSelectorNum, command, optionSetting, userRoutine)
  287. /*
  288.       TaskLevel
  289.       TaskLevel returns 0 if we're (probably) running at non-interrupt time.
  290.       There's no way to make this perfect, but this is as close as we can get.
  291.       If TaskLevel doesn't return 0, then the following masks can be used to learn more:
  292.            k68kInterruptLevelMask        = 0x00000007,
  293.            kInVBLTaskMask                = 0x00000010,
  294.            kInDeferredTaskMask            = 0x00000020,
  295.            kInSecondaryIntHandlerMask    = 0x00000040
  296. */
  297. EXTERN_API( UInt32 )
  298. TaskLevel                        (void)                                                        TWOWORDINLINE(0x7001, 0xAA7E);
  299.  
  300.  
  301. #define    ATTASKLEVEL0()    ( TaskLevel() == 0 )
  302.  
  303. /*
  304.       NewDebugComponent
  305.       NewDebugComponent registers a component with DebugLib.
  306.           Inputs:
  307.               componentSignature    The unique signature of component
  308.               componentName        The displayable string naming the component
  309.               componentCallback    The callback into component for working with options
  310.           Result:
  311.               noErr                            no error
  312.               memFullErr                        could not allocate memory
  313.               debuggingExecutionContextErr    routine cannot be called at this time
  314.               debuggingDuplicateSignatureErr    componentSignature already registered
  315.               debuggingInvalidNameErr            componentName is invalid (NULL)
  316. */
  317. EXTERN_API( OSStatus )
  318. NewDebugComponent                (OSType                 componentSignature,
  319.                                  ConstStr255Param         componentName,
  320.                                  DebugComponentCallbackUPP  componentCallback)                TWOWORDINLINE(0x7002, 0xAA7E);
  321.  
  322.  
  323. /*
  324.       NewDebugOption
  325.       NewDebugOption registers a debug option with DebugLib.
  326.           Inputs:
  327.               componentSignature    The signature of component to register a debug option for
  328.               optionSelectorNum    The selector number of this debug option
  329.               optionName            The displayable string naming this debug option
  330.           Result:
  331.               noErr                            no error
  332.               memFullErr                        could not allocate memory
  333.               debuggingExecutionContextErr    called at interrupt time
  334.               debuggingDuplicateOptionErr        optionSelectorNum already registered
  335.               debuggingInvalidSignatureErr    componentSignature not registered
  336.               debuggingInvalidNameErr            optionName is invalid (NULL)
  337.               debuggingNoCallbackErr            debugging component has no callback
  338. */
  339. EXTERN_API( OSStatus )
  340. NewDebugOption                    (OSType                 componentSignature,
  341.                                  SInt32                 optionSelectorNum,
  342.                                  ConstStr255Param         optionName)                            TWOWORDINLINE(0x7003, 0xAA7E);
  343.  
  344.  
  345. /*
  346.       DisposeDebugComponent
  347.       DisposeDebugComponent removes a component registration and all related debug options from DebugLib.
  348.           Input:
  349.               componentSignature    The unique signature of a component
  350.           Result:
  351.               noErr                            no error
  352.               debuggingExecutionContextErr    called at interrupt time
  353.               debuggingInvalidSignatureErr    componentSignature not registered
  354. */
  355. EXTERN_API( OSStatus )
  356. DisposeDebugComponent            (OSType                 componentSignature)                    TWOWORDINLINE(0x7004, 0xAA7E);
  357.  
  358.  
  359. /*
  360.       GetDebugComponentInfo
  361.       GetDebugComponentInfo returns a component registered with DebugLib.
  362.           Inputs:
  363.               index                The index into the list of registered components (1-based)
  364.           Outputs:
  365.               componentSignature    The unique signature of a component
  366.               componentName        The displayable string naming a component
  367.           Result:
  368.               noErr                            no error
  369.               debuggingNoMatchErr                debugging component not found at this index
  370. */
  371. EXTERN_API( OSStatus )
  372. GetDebugComponentInfo            (UInt32                 index,
  373.                                  OSType *                componentSignature,
  374.                                  Str255                 componentName)                        TWOWORDINLINE(0x7005, 0xAA7E);
  375.  
  376.  
  377. /*
  378.       GetDebugOptionInfo
  379.       GetDebugOptionInfo returns a debug option registered with DebugLib.
  380.           Inputs:
  381.               index                The index into the list of registered debug options (0-based);
  382.                                       0 = kComponentDebugOption 
  383.               componentSignature    The unique signature of a component
  384.           Outputs:
  385.               optionSelectorNum    The selector number of this debug option
  386.               optionName            The displayable string naming this debug option
  387.               optionSetting        The current debug option setting
  388.           Result:
  389.               noErr                            no error
  390.               debuggingInvalidSignatureErr    componentSignature not registered
  391.               debuggingNoMatchErr                option not found at this index
  392. */
  393. EXTERN_API( OSStatus )
  394. GetDebugOptionInfo                (UInt32                 index,
  395.                                  OSType                 componentSignature,
  396.                                  SInt32 *                optionSelectorNum,
  397.                                  Str255                 optionName,
  398.                                  Boolean *                optionSetting)                        TWOWORDINLINE(0x7006, 0xAA7E);
  399.  
  400.  
  401. /*
  402.       SetDebugOptionValue
  403.       SetDebugOptionValue sets a debug option registered with DebugLib.
  404.           Inputs:
  405.               componentSignature    The unique signature of a component
  406.               optionSelectorNum    The selector number of this debug option
  407.               newOptionSetting    The new debug option setting
  408.           Result:
  409.               noErr                            no error
  410.               debuggingInvalidSignatureErr    componentSignature not registered
  411.               debuggingInvalidOptionErr        optionSelectorNum is not registered
  412. */
  413. EXTERN_API( OSStatus )
  414. SetDebugOptionValue                (OSType                 componentSignature,
  415.                                  SInt32                 optionSelectorNum,
  416.                                  Boolean                 newOptionSetting)                    TWOWORDINLINE(0x7007, 0xAA7E);
  417.  
  418. /*
  419.       DebugAssertOutputHandler
  420.       DebugAssertOutputHandler is the callback that registers with DebugLib to handle the
  421.       output from DebugAssert.
  422.           Inputs:
  423.               "componentSignature" through "value" are the raw values passed to DebugAssert
  424.                   when an exception occurs.
  425.                outputMsg is the string DebugAssert build which would normally be passed to
  426.                   DebugStr if a DebugAssertOutputHandler isn't installed.
  427. */
  428. typedef CALLBACK_API( void , DebugAssertOutputHandlerProcPtr )(OSType componentSignature, UInt32 options, char *assertionString, char *exceptionString, char *errorString, char *fileName, long lineNumber, void *value, ConstStr255Param outputMsg);
  429. typedef STACK_UPP_TYPE(DebugAssertOutputHandlerProcPtr)         DebugAssertOutputHandlerUPP;
  430. #if OPAQUE_UPP_TYPES
  431.     EXTERN_API(DebugAssertOutputHandlerUPP)
  432.     NewDebugAssertOutputHandlerUPP    (DebugAssertOutputHandlerProcPtr userRoutine);
  433.  
  434.     EXTERN_API(void)
  435.     DisposeDebugAssertOutputHandlerUPP    (DebugAssertOutputHandlerUPP userUPP);
  436.  
  437.     EXTERN_API(void)
  438.     InvokeDebugAssertOutputHandlerUPP    (OSType            componentSignature,
  439.                                     UInt32                    options,
  440.                                     char *                    assertionString,
  441.                                     char *                    exceptionString,
  442.                                     char *                    errorString,
  443.                                     char *                    fileName,
  444.                                     long                    lineNumber,
  445.                                     void *                    value,
  446.                                     ConstStr255Param        outputMsg,
  447.                                     DebugAssertOutputHandlerUPP userUPP);
  448.  
  449. #else
  450.     enum { uppDebugAssertOutputHandlerProcInfo = 0x00FFFFC0 };         /* pascal no_return_value Func(4_bytes, 4_bytes, 4_bytes, 4_bytes, 4_bytes, 4_bytes, 4_bytes, 4_bytes, 4_bytes) */
  451.     #define NewDebugAssertOutputHandlerUPP(userRoutine)             (DebugAssertOutputHandlerUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), uppDebugAssertOutputHandlerProcInfo, GetCurrentArchitecture())
  452.     #define DisposeDebugAssertOutputHandlerUPP(userUPP)             DisposeRoutineDescriptor(userUPP)
  453.     #define InvokeDebugAssertOutputHandlerUPP(componentSignature, options, assertionString, exceptionString, errorString, fileName, lineNumber, value, outputMsg, userUPP)  CALL_NINE_PARAMETER_UPP((userUPP), uppDebugAssertOutputHandlerProcInfo, (componentSignature), (options), (assertionString), (exceptionString), (errorString), (fileName), (lineNumber), (value), (outputMsg))
  454. #endif
  455. /* support for pre-Carbon UPP routines: NewXXXProc and CallXXXProc */
  456. #define NewDebugAssertOutputHandlerProc(userRoutine)             NewDebugAssertOutputHandlerUPP(userRoutine)
  457. #define CallDebugAssertOutputHandlerProc(userRoutine, componentSignature, options, assertionString, exceptionString, errorString, fileName, lineNumber, value, outputMsg) InvokeDebugAssertOutputHandlerUPP(componentSignature, options, assertionString, exceptionString, errorString, fileName, lineNumber, value, outputMsg, userRoutine)
  458. /*
  459.       InstallDebugAssertOutputHandler
  460.       InstallDebugAssertOutputHandler installs a DebugAssertOutputHandler which DebugAssert calls
  461.       instead of DebugStr.
  462.           Inputs:
  463.               handler        the DebugAssertOutputHandler to install or NULL to switch back to
  464.                           the default handler (DebugStr).
  465. */
  466. EXTERN_API( void )
  467. InstallDebugAssertOutputHandler    (DebugAssertOutputHandlerUPP  handler)                        TWOWORDINLINE(0x7008, 0xAA7E);
  468.  
  469. /*______________________________________________________________________________________*/
  470. /*                                                                                        */
  471. /*    Tech Q&A PLAT-30 says to check bit 5 of the byte at 0xbff to                        */
  472. /*    determine whether Macsbug ( or any other low level debugger )                        */
  473. /*    is installed; I also check that MacJmp ( which points to the                        */
  474. /*    entry point for the debugger ) is not nil and not -1.                                */
  475. /*                                                                                        */
  476. /*    MacJmpFlag:                                                                            */
  477. /*        Bit 5 should be set to indicate the debugger is installed.                        */
  478. /*        Bit 6 should be set to indicate the debugger is initialized.                    */
  479. /*        Bit 7 should be clear to indicate that the debugger is NOT busy                    */
  480. /*                                                                                        */
  481. /*    Dr. Macsbug says to also check that the byte at 0xBFF isn't 0xFF.                    */
  482. /*______________________________________________________________________________________*/
  483.  
  484. #define LocalLMGetMacJmp() (*(( unsigned long *)0x0120))
  485. #define LocalLMGetMacJmpFlag() (*(( UInt8 *)0x0BFF))
  486.  
  487. #define    ISLOWLEVELDEBUGGERCALLABLE()                                    \
  488.     ( ( LocalLMGetMacJmpFlag() != (UInt8) 0xff ) &&                        \
  489.       ( (LocalLMGetMacJmpFlag() & (UInt8) 0xe0) == (UInt8) 0x60 ) &&    \
  490.       ( LocalLMGetMacJmp() != 0 ) &&                                     \
  491.        ( LocalLMGetMacJmp() != (unsigned long) 0xffffffff ) )
  492.     
  493. #if DEBUG
  494.     
  495. #define    DEBUGGER()                                                        \
  496.     do {                                                                \
  497.         if ( ISLOWLEVELDEBUGGERCALLABLE() )                                \
  498.             Debugger();                                                    \
  499.     } while ( false )
  500.     
  501. #define    DEBUGSTR(str)                                                    \
  502.     do {                                                                \
  503.         if ( ISLOWLEVELDEBUGGERCALLABLE() )                                \
  504.             DebugStr ( str );                                            \
  505.     } while ( false )
  506.  
  507. #else
  508.  
  509. #define    DEBUGGER()
  510.  
  511. #define    DEBUGSTR(str)
  512.  
  513. #endif
  514.  
  515.  
  516. /* no-op asserts for production code*/
  517.  
  518. #if DEBUGLEVEL == DEBUG_LEVEL_PRODUCTION
  519. #define check(assertion)
  520. #define check_string( assertion, cstring )
  521. #define check_noerr(err)
  522. #define check_noerr_string( error, cstring )
  523. #define debug_string( cstring )
  524. #define require( assertion, label )                                do { if( !(assertion) ) goto label; } while(false)
  525. #define require_string( assertion, label, string )                        require(assertion, label)
  526. #define require_quiet( assertion, label )                        require( assertion, label )
  527. #define require_noerr( error, label )                            do { if( (error) != noErr ) goto label; } while(false)
  528. #define require_noerr_quiet( assertion, label )                    require_noerr( assertion, label )
  529. #define require_noerr_action( error, label, action )            do { if( (error) != noErr ) { {action;}; goto label; } } while(false)
  530. #define require_noerr_action_quiet( assertion, label, action )    require_noerr_action( assertion, label, action )
  531. #define require_action( assertion, label, action )                        do { if( !(assertion) ) { {action;}; goto label; } } while(false)
  532. #define require_action_quiet( assertion, label, action )        require_action( assertion, label, action )
  533. #define require_action_string( assertion, label, action, cstring )                        do { if( !(assertion) ) { {action;}; goto label; } } while(false)
  534.  
  535. #else
  536.  
  537.  
  538. /*______________________________________________________________________________________*/
  539.  
  540. #define debug_string(string)                                             \
  541.     do {                                                                \
  542.         DEBUGASSERTMSG(COMPONENT_SIGNATURE, DEBUG_NO_OPTIONS,            \
  543.                     QuoteExceptionString(string), nil, nil,                \
  544.                     __FILE__, __LINE__, 0);                                 \
  545.     } while (false)
  546.  
  547. /*______________________________________________________________________________________*/
  548.  
  549. #define check(assertion)                                                 \
  550.     do {                                                                \
  551.         if (assertion) ;                                                \
  552.         else {                                                            \
  553.             DEBUGASSERTMSG(COMPONENT_SIGNATURE, DEBUG_NO_OPTIONS,        \
  554.                         QuoteExceptionString(assertion), nil, nil,        \
  555.                         __FILE__, __LINE__, 0);                             \
  556.         }                                                                \
  557.     } while (false)
  558.  
  559. /*______________________________________________________________________________________*/
  560.  
  561.  
  562.  
  563. #define check_string(assertion, cstring)                                             \
  564.     do {                                                                \
  565.         if (assertion) ;                                                \
  566.         else {                                                            \
  567.             DEBUGASSERTMSG(COMPONENT_SIGNATURE, DEBUG_NO_OPTIONS,        \
  568.                         QuoteExceptionString(assertion), cstring, nil,    \
  569.                         __FILE__, __LINE__, 0);                             \
  570.         }                                                                \
  571.     } while (false)
  572.  
  573.  
  574.  
  575. /*______________________________________________________________________________________*/
  576.  
  577. #define check_noerr(error)                                                     \
  578.     do {                                                                    \
  579.         OSStatus localError = error;                                        \
  580.         if (localError == noErr) ;                                            \
  581.         else {                                                                \
  582.             DEBUGASSERTMSG(COMPONENT_SIGNATURE, DEBUG_NO_OPTIONS,            \
  583.                         QuoteExceptionString(error) "== noErr", nil, nil,    \
  584.                         __FILE__, __LINE__, (void *)localError);             \
  585.         }                                                                    \
  586.     } while (false)
  587.  
  588. /*______________________________________________________________________________________*/
  589.  
  590. #define check_noerr_string(error, cstring)                                             \
  591.     do {                                                                            \
  592.         OSStatus localError = error;                                                \
  593.         if (localError == noErr) ;                                                    \
  594.         else {                                                                        \
  595.             DEBUGASSERTMSG(COMPONENT_SIGNATURE, DEBUG_NO_OPTIONS,                    \
  596.                         QuoteExceptionString(error) "== noErr\n", cstring, nil,    \
  597.                         __FILE__, __LINE__, (void *)localError);                     \
  598.         }                                                                            \
  599.     } while (false)
  600.  
  601. /*______________________________________________________________________________________*/
  602.  
  603. #define require(assertion, exception)                                      \
  604.     do {                                                                \
  605.         if (assertion) ;                                                \
  606.         else {                                                            \
  607.             DEBUGASSERTMSG(COMPONENT_SIGNATURE, DEBUG_NO_OPTIONS,         \
  608.                         QuoteExceptionString(assertion),                  \
  609.                         QuoteExceptionString(exception),                 \
  610.                         nil, __FILE__, __LINE__, 0);                    \
  611.             goto exception;                                                \
  612.         }                                                                \
  613.     } while (false)
  614.  
  615. /*______________________________________________________________________________________*/
  616.  
  617. #define require_noerr(error, exception)                                  \
  618.     do {                                                                \
  619.         OSStatus localError = error;                                    \
  620.         if (localError == noErr) ;                                        \
  621.         else {                                                            \
  622.             DEBUGASSERTMSG(COMPONENT_SIGNATURE, DEBUG_NO_OPTIONS,         \
  623.                         QuoteExceptionString(error) "== noErr",          \
  624.                         QuoteExceptionString(exception),                 \
  625.                         nil, __FILE__, __LINE__, (void *)localError );    \
  626.             goto exception;                                                \
  627.         }                                                                \
  628.     } while (false)
  629.  
  630. /*______________________________________________________________________________________*/
  631.  
  632. #define require_string(assertion, exception, string)                      \
  633.     do {                                                                \
  634.         if (assertion) ;                                                \
  635.         else {                                                            \
  636.             DEBUGASSERTMSG(COMPONENT_SIGNATURE, DEBUG_NO_OPTIONS,         \
  637.                         string, QuoteExceptionString(exception),         \
  638.                         QuoteExceptionString(exception),                 \
  639.                         __FILE__, __LINE__, 0 );        \
  640.             goto exception;                                                \
  641.         }                                                                \
  642.     } while (false)
  643.  
  644.  
  645. /*______________________________________________________________________________________*/
  646.  
  647. #define require_noerr_action(error, exception, action)                  \
  648.     do {                                                                \
  649.         OSStatus localError = error;                                    \
  650.         if (localError == noErr) ;                                        \
  651.         else {                                                            \
  652.             DEBUGASSERTMSG(COMPONENT_SIGNATURE, DEBUG_NO_OPTIONS,         \
  653.                         QuoteExceptionString(error) "== noErr",          \
  654.                         QuoteExceptionString(exception),                 \
  655.                         nil, __FILE__, __LINE__, (void *)localError );    \
  656.             { action; }                                                    \
  657.             goto exception;                                                \
  658.         }                                                                \
  659.     } while (false)
  660.  
  661. /*______________________________________________________________________________________*/
  662.  
  663. #define require_noerr_quiet(error, exception)                              \
  664.     do {                                                                \
  665.         if (error == noErr) ;                                            \
  666.         else {                                                            \
  667.             goto exception;                                                \
  668.         }                                                                \
  669.     } while (false)
  670.  
  671.  
  672. /*______________________________________________________________________________________*/
  673.  
  674. #define require_noerr_action_quiet(error, exception, action)              \
  675.     do {                                                                \
  676.         if (error == noErr) ;                                            \
  677.         else {                                                            \
  678.             { action; }                                                    \
  679.             goto exception;                                                \
  680.         }                                                                \
  681.     } while (false)
  682.  
  683.  
  684. /*______________________________________________________________________________________*/
  685.  
  686. #define require_action(assertion, exception, action)                  \
  687.     do {                                                            \
  688.         if (assertion) ;                                            \
  689.         else {                                                        \
  690.             DEBUGASSERTMSG(COMPONENT_SIGNATURE, DEBUG_NO_OPTIONS,         \
  691.                         QuoteExceptionString(assertion),              \
  692.                         QuoteExceptionString(exception),            \
  693.                         nil, __FILE__, __LINE__, 0);                 \
  694.             { action; }                                                \
  695.             goto exception;                                            \
  696.         }                                                            \
  697.     } while (false)
  698.  
  699. /*______________________________________________________________________________________*/
  700.  
  701. #define require_action_string(assertion, exception, action, cstring)      \
  702.     do {                                                                \
  703.         if (assertion) ;                                                \
  704.         else {                                                            \
  705.             DEBUGASSERTMSG(COMPONENT_SIGNATURE, DEBUG_NO_OPTIONS,         \
  706.                         cstring ": " QuoteExceptionString(assertion),    \
  707.                         QuoteExceptionString(exception),                \
  708.                         nil, __FILE__, __LINE__, 0);                     \
  709.             { action; }                                                    \
  710.             goto exception;                                                \
  711.         }                                                                \
  712.     } while (false)
  713.  
  714. /*______________________________________________________________________________________*/
  715.  
  716. #define require_quiet(assertion, exception)                          \
  717.     do {                                                            \
  718.         if (assertion) ;                                            \
  719.         else {                                                        \
  720.             goto exception;                                            \
  721.         }                                                            \
  722.     } while (false)
  723.  
  724.  
  725. /*______________________________________________________________________________________*/
  726.  
  727. #define require_action_quiet(assertion, exception, action)             \
  728.     do {                                                            \
  729.         if (assertion) ;                                            \
  730.         else {                                                        \
  731.             { action; }                                                \
  732.             goto exception;                                            \
  733.         }                                                            \
  734.     } while (false)
  735.  
  736.  
  737.  
  738. #endif /* DEBUG_LEVEL_PRODUCTION */
  739.  
  740. /*    Define these in terms of the check() and require macros.  In non-debug builds, the check calls
  741.     go away and the require macros are mostly checks and jumps.
  742. */
  743. #define check_tasklevel0( )                                            check( ATTASKLEVEL0() )
  744. #define check_tasklevel0_string( string )                            check_string( ATTASKLEVEL0(), string )
  745.  
  746. #define require_tasklevel0( label )                                    require( ATTASKLEVEL0(), label )
  747. #define require_tasklevel0_string( label, string )                    require_string( ATTASKLEVEL0(), label, string )
  748. #define require_tasklevel0_action( label, string, action )            require_action( ATTASKLEVEL0(), label, action )
  749. #define require_tasklevel0_action_string( label, string, action )    require_action_string( ATTASKLEVEL0(), label, action, string )
  750.  
  751.  
  752. /*______________________________________________________________________________________*/
  753.  
  754. #if DEBUGLEVEL > DEBUG_LEVEL_PRODUCTION
  755.     #define verify(assertion)        check(assertion)
  756.     #define verify_noerr(assertion)    check_noerr( (assertion) )
  757. #else
  758.     #define verify(assertion)        do { (void) (assertion); } while (0)
  759.     #define verify_noerr(assertion)    verify(assertion)
  760. #endif
  761.  
  762.  
  763.  
  764. /*______________________________________________________________________________________*/
  765.  
  766. #define ncheck(assertion)                                        check( !(assertion) )
  767. #define ncheck_string(assertion, cstring)                        check_string( !(assertion), cstring )
  768. #define nrequire(assertion, exception)                            require( !(assertion), exception )
  769. #define nrequire_action(assertion, exception, action)            require_action( !(assertion), exception, action )
  770. #define nrequire_quiet(assertion, exception)                    require_quiet( !(assertion), exception )
  771. #define nrequire_action_quiet(assertion, exception, action)        require_action_quiet( !(assertion), exception, action )
  772. #define nrequire_string(assertion, exception, string)            require_string( !(assertion), exception, string )
  773.  
  774.  
  775.  
  776.  
  777.  
  778. #if PRAGMA_STRUCT_ALIGN
  779.     #pragma options align=reset
  780. #elif PRAGMA_STRUCT_PACKPUSH
  781.     #pragma pack(pop)
  782. #elif PRAGMA_STRUCT_PACK
  783.     #pragma pack()
  784. #endif
  785.  
  786. #ifdef PRAGMA_IMPORT_OFF
  787. #pragma import off
  788. #elif PRAGMA_IMPORT
  789. #pragma import reset
  790. #endif
  791.  
  792. #ifdef __cplusplus
  793. }
  794. #endif
  795.  
  796. #endif /* __DEBUGGING__ */
  797.  
  798.